 #!/bin/bash
# ranhaoliu 2021-8-20

#APP declaration
APP_NAME="${0##*[\\/]}"
APP_VERSION="1.0"


#颜色定义
cRed=1
cGreen=2
cYellow=3
cBlue=4
cFuchsia=5
cCyan=6
cWhite=7
colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)

#位置和大小
iLeft=3
iTop=2
#两个小括号表示算数运算符
((iTrayLeft = iLeft + 2))
((iTrayTop = iTop + 1))
((iTrayWidth = 10))
((iTrayHeight = 15))

#颜色设置
cBorder=$cGreen
cScore=$cFuchsia
cScoreValue=$cCyan

#控制信号
#该游戏使用两个进程，一个用于接收输入，一个用于游戏流程和显示界面;
#当前者接收到上下左右等按键时，通过向后者发送signal的方式通知后者。
sigRotate=25
sigLeft=26
sigRight=27
sigDown=28
sigAllDown=29
sigExit=30

#七种不同的方块的定义
#通过旋转，每种方块显示的样式可能有几种
box0=(0 0 0 1 1 0 1 1)
box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)
#所有其中方块的定义都放到box变量中
box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})
#各种方块旋转后可能的样式数目
countBox=(1 2 2 2 4 4 4)
#各种方块在box数组中的偏移
offsetBox=(0 1 3 5 7 11 15)

#每提高一个速度级需要积累的分数
iScoreEachLevel=50        #be greater than 7

#运行时数据
sig=0                #接收到的signal
iScore=0        #总分
iLevel=0        #速度级
boxNew=()        #新下落的方块的位置定义
cBoxNew=0        #新下落的方块的颜色
iBoxNewType=0        #新下落的方块的种类
iBoxNewRotate=0        #新下落的方块的旋转角度
boxCur=()        #当前方块的位置定义
cBoxCur=0        #当前方块的颜色
iBoxCurType=0        #当前方块的种类
iBoxCurRotate=0        #当前方块的旋转角度
boxCurX=-1        #当前方块的x坐标位置
boxCurY=-1        #当前方块的y坐标位置



 
#DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。
function DrawCurBox()
{
    local i j t bDraw sBox s
    bDraw=$1

    s=""
    if (( bDraw == 0 ))
    then
        sBox="\040\040"
    else
        sBox="[]"
        s=$s"\033[1m\033[7m\033[3${cBoxCur}m\033[4${cBoxCur}m"
    fi

    for ((j = 0; j < 8; j += 2))
    do
        ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY))
        ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]})))
        #\033[y;xH, 光标到(x, y)处
        s=$s"\033[${i};${t}H${sBox}"
    done 
    s=$s"\033[0m"
    echo -n $s
}


#更新新的方块
function RandomBox()
{
    local i j t
 
    #更新当前移动的方块
    iBoxCurType=${iBoxNewType}
    iBoxCurRotate=${iBoxNewRotate}
    cBoxCur=${cBoxNew}
    # 第一次调用 RandomBox()，${#boxNew[@]} 的值是0,第二次的值是8
    for ((j = 0; j < ${#boxNew[@]}; j++))
    do
        boxCur[$j]=${boxNew[$j]}
    done
 

    #显示当前移动的方块  (第一次调用RandomBox, 不执行这条if语句)
    if (( ${#boxCur[@]} == 8 ))
    then
        #计算当前方块该从顶端哪一行"冒"出来
        for ((j = 0, t = 4; j < 8; j += 2))
        do
            if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
        done
        ((boxCurY = -t))
        for ((j = 1, i = -4, t = 20; j < 8; j += 2))
        do
            if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi
            if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
        done
        ((boxCurX = (iTrayWidth - 1 - i - t) / 2))

        #显示当前移动的方块
        echo -ne `DrawCurBox 1`

        #如果方块一出来就没处放，Game over!
        # if ! BoxMove $boxCurY $boxCurX
        # then
        #     kill -$sigExit ${PPID}
        #     ShowExit
        # fi
    fi



    #清除右边预显示的方块
    for ((j = 0; j < 4; j++))
    do
        ((i = iTop + 1 + j))
        ((t = iLeft + 2 * iTrayWidth + 7))
        echo -ne "\033[${i};${t}H        "
    done

    #随机产生新的方块
    ((iBoxNewType = RANDOM % ${#offsetBox[@]})) # 产生 7以内的随机数
    ((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]})) # 1 2 2 2 4 4 4
    for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++))
    do
        boxNew[$j]=${box[$i]}; #  box0=(0 0 0 1 1 0 1 1)
    done
     
    ((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]})) # 颜色

    #显示右边预显示的方块
    echo -ne "\033[1m\033[7m\033[3${cBoxNew}m\033[4${cBoxNew}m"
    for ((j = 0; j < 8; j += 2))
    do
        ((i = iTop + 1 + ${boxNew[$j]}))
        ((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]}))
        echo -ne "\033[${i};${t}H[]"
    done
    echo -ne "\033[0m"
}

RandomBox
RandomBox
